"use client"

import { useState } from "react"

import type React from "react"
import { createContext, useContext, useCallback, useRef, useEffect, useReducer } from "react"
import type { Song } from "@/types/song"
import { toast } from "@/components/ui/use-toast"

interface PlayerState {
  currentSong: Song | null
  isPlaying: boolean
  volume: number
  progress: number
  isMuted: boolean
  queue: Song[]
  shuffledQueue: Song[]
  isShuffle: boolean
  isLoop: boolean
}

type PlayerAction =
    | { type: "SET_CURRENT_SONG"; payload: Song | null }
    | { type: "SET_IS_PLAYING"; payload: boolean }
    | { type: "SET_VOLUME"; payload: number }
    | { type: "SET_PROGRESS"; payload: number }
    | { type: "SET_IS_MUTED"; payload: boolean }
    | { type: "SET_QUEUE"; payload: Song[] }
    | { type: "SET_SHUFFLED_QUEUE"; payload: Song[] }
    | { type: "SET_IS_SHUFFLE"; payload: boolean }
    | { type: "SET_IS_LOOP"; payload: boolean }
    | { type: "ADD_TO_QUEUE"; payload: Song }
    | { type: "REMOVE_FROM_QUEUE"; payload: number }
    | { type: "CLEAR_QUEUE" }
    | { type: "TOGGLE_FAVORITE"; payload: Song }
    | { type: "REMOVE_SONG"; payload: number }

interface PlayerContextType {
  state: PlayerState
  dispatch: React.Dispatch<PlayerAction>
  playSong: (song: Song) => void
  playQueue: (songs: Song[]) => void
  togglePlay: () => void
  setVolume: (volume: number) => void
  setProgress: (progress: number) => void
  nextSong: () => void
  previousSong: () => void
  toggleMute: () => void
  toggleShuffle: () => void
  toggleLoop: () => void
  addToQueue: (song: Song) => void
  removeFromQueue: (songId: number) => void
  clearQueue: () => void
  toggleFavorite: (song: Song) => void
  removeSong: (index: number) => void
}

const PlayerContext = createContext<PlayerContextType | undefined>(undefined)

const playerReducer = (state: PlayerState, action: PlayerAction): PlayerState => {
  switch (action.type) {
    case "SET_CURRENT_SONG":
      return { ...state, currentSong: action.payload }
    case "SET_IS_PLAYING":
      return { ...state, isPlaying: action.payload }
    case "SET_VOLUME":
      return { ...state, volume: action.payload }
    case "SET_PROGRESS":
      return { ...state, progress: action.payload }
    case "SET_IS_MUTED":
      return { ...state, isMuted: action.payload }
    case "SET_QUEUE":
      return { ...state, queue: action.payload }
    case "SET_SHUFFLED_QUEUE":
      return { ...state, shuffledQueue: action.payload }
    case "SET_IS_SHUFFLE":
      return { ...state, isShuffle: action.payload }
    case "SET_IS_LOOP":
      return { ...state, isLoop: action.payload }
    case "ADD_TO_QUEUE":
      // 检查歌曲是否已经在队列中
      if (!state.queue.some((song) => song.id === action.payload.id)) {
        return { ...state, queue: [...state.queue, action.payload] }
      }
      return state // 如果歌曲已存在，不做任何改变
    case "REMOVE_FROM_QUEUE":
      return { ...state, queue: state.queue.filter((song) => song.id !== action.payload) }
    case "CLEAR_QUEUE":
      return { ...state, queue: [], shuffledQueue: [] }
    case "TOGGLE_FAVORITE":
      return {
        ...state,
        queue: state.queue.map((s) => (s.id === action.payload.id ? { ...s, isLiked: !s.isLiked } : s)),
      }
    case "REMOVE_SONG": {
      const newQueue = [...state.queue]
      newQueue.splice(action.payload, 1)
      return { ...state, queue: newQueue }
    }
    default:
      return state
  }
}

export const PlayerProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
  const [state, dispatch] = useReducer(playerReducer, {
    currentSong: null,
    isPlaying: false,
    volume: 1,
    progress: 0,
    isMuted: false,
    queue: [],
    shuffledQueue: [],
    isShuffle: false,
    isLoop: false,
  })

  const audioRef = useRef<HTMLAudioElement | null>(null)
  const [originalQueue, setOriginalQueue] = useState<Song[]>([])

  useEffect(() => {
    const audio = audioRef.current
    if (state.currentSong && audio) {
      audio.src = state.currentSong.url
      audio.load()
      if (state.isPlaying) {
        audio.play().catch((error) => {
          console.error("Playback failed:", error)
        })
      }
    }
  }, [state.currentSong, state.isPlaying])

  useEffect(() => {
    const audio = audioRef.current
    if (audio) {
      audio.volume = state.volume
      audio.muted = state.isMuted
    }
  }, [state.volume, state.isMuted])

  const playSong = useCallback(
      (song: Song) => {
        dispatch({ type: "SET_CURRENT_SONG", payload: song })
        dispatch({ type: "SET_IS_PLAYING", payload: true })
      },
      [dispatch],
  )

  const playQueue = useCallback(
      (songs: Song[]) => {
        setOriginalQueue(songs)
        dispatch({ type: "SET_QUEUE", payload: songs })
        dispatch({
          type: "SET_SHUFFLED_QUEUE",
          payload: state.isShuffle ? [...songs].sort(() => Math.random() - 0.5) : songs,
        })
        dispatch({ type: "SET_CURRENT_SONG", payload: songs[0] })
        dispatch({ type: "SET_IS_PLAYING", payload: true })
      },
      [dispatch, state.isShuffle],
  )

  const togglePlay = useCallback(() => {
    dispatch({ type: "SET_IS_PLAYING", payload: !state.isPlaying })
    const audio = audioRef.current
    if (audio) {
      if (!state.isPlaying) {
        audio.play().catch((error) => {
          console.error("Playback failed:", error)
        })
      } else {
        audio.pause()
      }
    }
  }, [state.isPlaying, dispatch])

  const setVolume = useCallback(
      (volume: number) => {
        dispatch({ type: "SET_VOLUME", payload: volume })
      },
      [dispatch],
  )

  const setProgress = useCallback(
      (progress: number) => {
        const audio = audioRef.current
        if (audio && isFinite(audio.duration) && isFinite(progress)) {
          dispatch({ type: "SET_PROGRESS", payload: progress })
          audio.currentTime = progress * audio.duration
        }
      },
      [dispatch],
  )

  const nextSong = useCallback(() => {
    if (state.queue.length === 0) return

    const currentQueue = state.isShuffle ? state.shuffledQueue : state.queue
    const currentIndex = currentQueue.findIndex((song) => song.id === state.currentSong?.id)
    const nextIndex = (currentIndex + 1) % currentQueue.length
    const nextSong = currentQueue[nextIndex]

    dispatch({ type: "SET_CURRENT_SONG", payload: nextSong })
    dispatch({ type: "SET_IS_PLAYING", payload: true })
  }, [state.queue, state.currentSong, state.isShuffle, state.shuffledQueue, dispatch])

  const previousSong = useCallback(() => {
    if (state.queue.length === 0) return

    const currentQueue = state.isShuffle ? state.shuffledQueue : state.queue
    const currentIndex = currentQueue.findIndex((song) => song.id === state.currentSong?.id)
    const previousIndex = (currentIndex - 1 + currentQueue.length) % currentQueue.length
    const previousSong = currentQueue[previousIndex]

    dispatch({ type: "SET_CURRENT_SONG", payload: previousSong })
    dispatch({ type: "SET_IS_PLAYING", payload: true })
  }, [state.queue, state.currentSong, state.isShuffle, state.shuffledQueue, dispatch])

  const toggleMute = useCallback(() => {
    dispatch({ type: "SET_IS_MUTED", payload: !state.isMuted })
  }, [dispatch, state.isMuted])

  const toggleShuffle = useCallback(() => {
    const newShuffleState = !state.isShuffle
    const newShuffledQueue = newShuffleState ? [...state.queue].sort(() => Math.random() - 0.5) : state.queue

    toast({
      title: newShuffleState ? "已切换到随机播放" : "已切换到顺序播放",
    })

    dispatch({ type: "SET_IS_SHUFFLE", payload: newShuffleState })
    dispatch({ type: "SET_SHUFFLED_QUEUE", payload: newShuffledQueue })
  }, [state.isShuffle, state.queue, dispatch])

  const toggleLoop = useCallback(() => {
    const newLoopState = !state.isLoop

    toast({
      title: newLoopState ? "已切换到单曲循环" : "已切换到顺序播放",
    })

    dispatch({ type: "SET_IS_LOOP", payload: newLoopState })
  }, [dispatch, state.isLoop])

  const addToQueue = useCallback(
      (song: Song) => {
        dispatch({ type: "ADD_TO_QUEUE", payload: song })
      },
      [dispatch],
  )

  const removeFromQueue = useCallback(
      (songId: number) => {
        dispatch({ type: "REMOVE_FROM_QUEUE", payload: songId })
      },
      [dispatch],
  )

  const clearQueue = useCallback(() => {
    dispatch({ type: "CLEAR_QUEUE" })
  }, [dispatch])

  const toggleFavorite = useCallback(
      (song: Song) => {
        dispatch({ type: "TOGGLE_FAVORITE", payload: song })
        toast({
          title: song.isLiked ? "已从我喜欢的音乐中移除" : "已添加到我喜欢的音乐",
          description: `${song.title} - ${song.artists}`,
        })
      },
      [dispatch],
  )

  const removeSong = useCallback(
      (index: number) => {
        dispatch({ type: "REMOVE_SONG", payload: index })
        const newQueue = [...state.queue]
        const removedSong = newQueue.splice(index, 1)[0]
        toast({
          title: "已从播放列表中移除",
          description: removedSong.title,
        })
      },
      [dispatch, state.queue],
  )

  return (
      <PlayerContext.Provider
          value={{
            state,
            dispatch,
            playSong,
            playQueue,
            togglePlay,
            setVolume,
            setProgress,
            nextSong,
            previousSong,
            toggleMute,
            toggleShuffle,
            toggleLoop,
            addToQueue,
            removeFromQueue,
            clearQueue,
            toggleFavorite,
            removeSong,
          }}
      >
        {children}
        <audio
            ref={audioRef}
            onTimeUpdate={() => {
              const audio = audioRef.current
              if (audio) {
                dispatch({ type: "SET_PROGRESS", payload: audio.currentTime / audio.duration })
              }
            }}
            onEnded={() => {
              if (state.isLoop) {
                const audio = audioRef.current
                if (audio) {
                  audio.currentTime = 0
                  audio.play().catch((error) => {
                    console.error("Playback failed:", error)
                  })
                }
              } else {
                nextSong()
              }
            }}
        />
      </PlayerContext.Provider>
  )
}

export const usePlayer = () => {
  const context = useContext(PlayerContext)
  if (!context) {
    throw new Error("usePlayer must be used within a PlayerProvider")
  }

  const {
    state,
    dispatch,
    togglePlay,
    nextSong,
    previousSong,
    setVolume,
    setProgress,
    addToQueue,
    playSong,
    playQueue,
    toggleFavorite,
    removeSong,
    clearQueue,
    toggleShuffle,
    toggleLoop,
    toggleMute,
    removeFromQueue,
  } = context

  return {
    state,
    togglePlay,
    nextSong,
    previousSong,
    setVolume,
    setProgress,
    addToQueue,
    playSong,
    playQueue,
    toggleFavorite,
    removeSong,
    clearQueue,
    toggleShuffle,
    toggleLoop,
    toggleMute,
    removeFromQueue,
  }
}

export const usePlayerContext = usePlayer

